package com.milageincrease.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.milageincrease.api.HBaseWriteTools;
import com.milageincrease.dao.DataStationDao;
import com.milageincrease.entity.Car;
import com.milageincrease.entity.HbasesData;
import org.apache.avro.data.Json;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.QualifierFilter;
import org.apache.hadoop.hbase.filter.RegexStringComparator;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 计算所有小车每天里程增量和
 * */
@Configuration      //1.主要用于标记配置类，兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
public class IncreaseMileageCalculation {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //private String redisKey = "accumulated_mileage";
    private String redisKeyIns="increased_mileage";

    @Autowired
    private DataStationDao dataStationDao;

    @Autowired
    private Connection connection;


    @Scheduled(cron = "0 9 02 * * ?")
    public void add() throws Exception {
        //计算增量
        List<Car> cars = getIncrease();
        String ins=JSON.toJSONString(cars);

        Integer yesterdayDate = Integer.valueOf(getDate()) - 1;

        if (stringRedisTemplate.hasKey(redisKeyIns)) {
            List<String> accumulatedMileageTimes = JSONObject.parseArray(
                    stringRedisTemplate.opsForHash().get(redisKeyIns, "time").toString(),
                    String.class
            );

            List<String> accumulatedMileageDatas = JSONObject.parseArray(
                    stringRedisTemplate.opsForHash().get(redisKeyIns, "data").toString(),
                    String.class
            );

            accumulatedMileageTimes.add(yesterdayDate.toString());

            accumulatedMileageDatas.add(ins);

            stringRedisTemplate.opsForHash().put(redisKeyIns, "time", JSONObject.toJSONString(accumulatedMileageTimes));
            stringRedisTemplate.opsForHash().put(redisKeyIns, "data", JSONObject.toJSONString(accumulatedMileageDatas));
        } else {
            List<String> accumulatedMileageTimes = new ArrayList<>();

            List<String> accumulatedMileageDatas = new ArrayList<>();

            accumulatedMileageTimes.add(yesterdayDate.toString());

            accumulatedMileageDatas.add(ins);

            stringRedisTemplate.opsForHash().put(redisKeyIns, "time", JSONObject.toJSONString(accumulatedMileageTimes));
            stringRedisTemplate.opsForHash().put(redisKeyIns, "data", JSONObject.toJSONString(accumulatedMileageDatas));
        }

        HbasesData hbasesData = new HbasesData();
        hbasesData.setRowkey(String.valueOf(System.currentTimeMillis()));
        Map<String, Map<String, Object>> map = new HashMap<>();

        Map<String, Object> data = new HashMap<>();

        data.put("time", yesterdayDate);
        data.put("data", ins);

        map.put("day", data);
        hbasesData.setData(map);

        HBaseWriteTools tools = new HBaseWriteTools(redisKeyIns);
        tools.put(JSONObject.parseObject
                (JSONObject.toJSONString(hbasesData))
        );
        tools.close();
    }


    /**
     * 计算所有小车每天里程增量
     * */
    private List<Car> getIncrease() throws Exception {
        Double ins=0D;
        List<Car> res=new ArrayList<>();

        // 数据库中所有车的id集合
        List<Integer> idList = dataStationDao.listVehicleId();

        //前一天的开始时间与结束时间 2020-02-17 00:00:00~2020-02-17 23:59:59
        String max=getEndOfDay(getDateBefore());
        String min=getStartOfDay(getDateBefore());
        //时间戳
        String startTime=dateToStamp(min);
        String endTime=dateToStamp(max);

        for(Integer id:idList){
            List<Double> l=getOneList(id,startTime,endTime);
            //System.out.println("------------"+id+"-------------------");
            if(l.size()>1){
                //排序
                Collections.sort(l, new Comparator<Double>() {
                    @Override
                    public int compare(Double o1, Double o2) {
                        return o1.compareTo(o2);
                    }
                });
                Double re1=l.get(l.size()-1)-l.get(0);
                res.add(new Car(id,re1));
                //System.out.println(id+":"+re1);
            }
        }
        return res;
    }

    /**从Hbase获取数据*/
    private List<Double> getOneList(Integer id,String starttime,String endtime) throws Exception {
        String startRowKey;
        String endRowKey;
        String fcVoltageValue = "";
        String fcCurrentValue = "";
        Scan scan =new Scan();
        List<Double> res=new ArrayList<>();

//        startRowKey = String.format("2000110:1429734400000");
//        endRowKey = String.format("2000110:1629648000000");
        endRowKey = String.format(id+":"+starttime);
        startRowKey = String.format(id+":"+endtime);
        scan.setReversed(true);
        scan.withStartRow(startRowKey.getBytes());
        scan.withStopRow(endRowKey.getBytes());

        Filter currFilter = new QualifierFilter(CompareOperator.EQUAL, new RegexStringComparator(".*VEH\\.Odometer.*"));
        scan.setFilter(currFilter);
        Table table = connection.getTable(TableName.valueOf("data:hydrogen_vehicle_data"));

        ResultScanner scanner = table.getScanner(scan);
        table.close();

        for (Result result : scanner) {
            // System.out.println(Bytes.toString(result.getRow())+endtime);

            for (Cell cell : result.listCells()) {
                // 获取单元格的列名
                String cn = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength());
                if (cn.contains("VEH.Odometer")) {
                    // 获取单元格的值
                    fcVoltageValue = Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength());
                }
            }
            if (Double.valueOf(fcVoltageValue) > 0 ){
                Double aDouble = Double.valueOf(fcVoltageValue);
                res.add(aDouble);
            }else if (Double.valueOf(fcVoltageValue) < 0){
                fcVoltageValue = "0.0";
                res.add(0.0);
            }
        }

        return res;
    }

    /**
     * 获取前一天时间
     * */
    public static Date getDateBefore(){
        Date dNow = new Date();   //当前时间
        Date dBefore = new Date();
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(dNow);//把当前时间赋给日历
        calendar.add(Calendar.DAY_OF_MONTH, -1);  //设置为前一天
        dBefore = calendar.getTime();   //得到前一天的时间

        return dBefore;
    }
    // 返回时间格式如：2020-02-17 00:00:00
    public static String getStartOfDay(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }
    // 返回时间格式如：2020-02-19 23:59:59
    public static String getEndOfDay(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }
    /**
     * 将时间转换为时间戳
     * */
    public static String dateToStamp(String s) throws ParseException {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }
    /**
     * 获取当前时间
     * */
    public String getDate(){
        SimpleDateFormat df = new SimpleDateFormat("yyMMdd");//设置日期格式
        return df.format(new Date());
    }
}
